package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.dao.CategoryDao;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.Employee;
import com.itheima.reggie.entity.Setmeal;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishService;
import com.itheima.reggie.service.SetmealService;
import com.itheima.reggie.web.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.List;

/**
 * 分类业务层实现类
 *
 * @Author Vsunks.v
 * @Date 2022/8/14 9:09
 * @Blog blog.sunxiaowei.net/996.mba
 * @Description: 分类业务层实现类
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, Category> implements CategoryService {

    @Autowired
    CategoryDao categoryDao;


    @Autowired
    DishService dishService;

    @Autowired
    SetmealService setmealService;

    /**
     * 保存分类，保存时检查名称是否重复
     *
     * @param category 待保存到分类
     * @return
     */
    @Override
    public boolean saveWithNameCheck(Category category) {
        // 根据名称查询（全局分类不重名）
        // ~~根据名称和type值查询（菜品分类中或者套餐分类中不重名）~~
        //  查到，重复，抛业务异常
        checkDuplicateName(category);

        // 查不到，新增添加
        // 返回结果
        return this.save(category);
    }

    /**
     * 分页查询分类，并脱敏
     *
     * @param pageNum  页码
     * @param pageSize 页面大小
     * @return 分页对象
     */
    @Override
    public Page<Category> page(Integer pageNum, Integer pageSize) {

        // 封装分页对象
        Page<Category> page = new Page<>(pageNum, pageSize);

        // 封装查询条件（隐含条件）
        LambdaQueryWrapper<Category> lqw = Wrappers.lambdaQuery(Category.class);
        lqw.orderByAsc(Category::getSort).orderByDesc(Category::getUpdateTime);

        // 查询
        this.page(page, lqw);

        // 查询并脱敏
        // 无需脱敏，公共字段已经通过注解实现了脱敏

        return page;
    }


    /**
     * 修改分类，名称不能和其他已有名称重复
     *
     * @param category 要修改的分类信息
     * @return 是否修改成功
     */
    @Override
    public boolean updateByIdWithNameCheck(Category category) {

        // 检查是否重复
        checkDuplicateName(category);

        // 更新
        return this.updateById(category);
    }

    /**
     * 根据分类类型(套餐分类/菜品分类)查询该类型下所有的分类
     * @param type  类型id
     * @return      所有符合要求的分类的集合
     */
    @Override
    public List<Category> listByType(Integer type) {
        // 构建查询条件对象
        LambdaQueryWrapper<Category> lqw = Wrappers.lambdaQuery(Category.class);

        // 设置条件
        lqw.eq(Category::getType,type)
                .orderByAsc(Category::getSort)
                .orderByDesc(Category::getUpdateTime);

        // 查询
        // 返回数据
        return this.list(lqw);
    }


    /**
     * 检查名称是否重复，兼容更新和添加，包括修改的时候不修改名称
     *
     * @param category
     */
    private void checkDuplicateName(Category category) {
        // 根据用户名查询
        LambdaQueryWrapper<Category> lqw = Wrappers.lambdaQuery(Category.class);
        String name = category.getName();
        // lqw.eq(StringUtils.isNotBlank(name), Employee::getUsername, name);
        lqw.eq(Category::getName, name);
        Category categoryInDb = categoryDao.selectOne(lqw);


        // 判断对象是否为空，不为空则表示名称重复了，需要抛异常
        if (categoryInDb != null) {
            // 避免查询到自己之后产生的bug
            if (!categoryInDb.getId().equals(category.getId())) {
                throw new BusinessException("分类名称：" + name + "重复");
            }
        }
    }


    /**
     * 重写方法，添加判断是否在使用的逻辑；如果该分类在使用，则删除失败
     *
     * @param id 要删除的分类Id
     * @return 删除是否成功
     */
    @Override
    public boolean removeById(Serializable id) {

        // 如果分类在使用，禁止删除
        // 根据分类id查询套餐和菜品
        // 构建查询条件对象
        // 如果能查到任意一个，则表示在使用。抛出异常
        LambdaQueryWrapper<Dish> dlqw = Wrappers.lambdaQuery(Dish.class);
        dlqw.eq(Dish::getCategoryId, id);
        int dCount = dishService.count(dlqw);
        if (dCount > 0) {
            throw new BusinessException("该分类关联了菜品，无法删除");
        }

        LambdaQueryWrapper<Setmeal> slqw = Wrappers.lambdaQuery(Setmeal.class);
        slqw.eq(Setmeal::getCategoryId, id);
        int sCount = setmealService.count(slqw);
        if (sCount > 0) {
            throw new BusinessException("该分类关联了套餐，无法删除");
        }

        // 删除!!!!!!!!这里不能调用removeById，否则无限递归
        return categoryDao.deleteById(id) > 0;


    }
}
